#include "memory.h"
#include "AT24C1024.h"
#include "board_config.h"
#include "Private_Sensor.h"
#include <libmaple/bkp.h>
#include "Periph.h"
#include "User_CRC8.h"

//EEPROM最大存储记录数
unsigned int EPMaxRecord = (TABLE_SIZE - EEPROM_BASE_ADDR) / sizeof(SENSOR_DATA) - 1;

// Create an EDB object with the appropriate write and read handlers
void writer(unsigned long address, unsigned char data)
{
	EEPROM1024.write(address, data);
}

unsigned char reader(unsigned long address)
{
	return EEPROM1024.read(address);
}

EDB EpromDb(&writer, &reader);

/*
 *brief   : 保存本机ID到备份寄存器中
 *para    : 无
 *return  : 布尔值
 */
bool Save_HostID(unsigned char *sys_hostID)
{
	bkp_enable_writes();
	delay(10);
	for (unsigned char i = 0; i < 4; i++)
		bkp_write(SYS_HOSTID_BASE_ADDR + i, sys_hostID[i]);

	unsigned char ID_Verify = GetCrc8(&sys_hostID[0], 4);

	bkp_write(SYS_HOSTID_VERIFY, ID_Verify);

	for (unsigned char i = 0; i < 4; i++)
		if (sys_hostID[i] != bkp_read(SYS_HOSTID_BASE_ADDR + i))
			return false;

	return true;
}

/*
 *brief   : 保存本机ID另一份备份到备份寄存器中
 *para    : 无
 *return  : 布尔值
 */
bool Save_BKP_HostID(unsigned char *sys_hostID)
{
	bkp_enable_writes();
	delay(10);
	for (unsigned char i = 0; i < 4; i++)
		bkp_write(SYS_HOSTID_BKP_BASE_ADDR + i, sys_hostID[i]);

	unsigned char ID_Verify = GetCrc8(&sys_hostID[0], 4);

	bkp_write(SYS_HOSTID_BKP_VERIFY, ID_Verify);

	for (unsigned char i = 0; i < 4; i++)
		if (sys_hostID[i] != bkp_read(SYS_HOSTID_BKP_BASE_ADDR + i))
			return false;

	return true;
}

/*
 *brief   : 从备份寄存器读取一份本机ID
 *para    : 无
 *return  : 布尔值
 */
bool Read_HostID(unsigned char *sys_hostID)
{
	for (unsigned char i = 0; i < 4; i++)
		sys_hostID[i] = bkp_read(SYS_HOSTID_BASE_ADDR + i);

	unsigned char ID_Verify = bkp_read(SYS_HOSTID_VERIFY);
	unsigned char ID_Verify_Temp = GetCrc8(&sys_hostID[0], 4);

	if (ID_Verify != ID_Verify_Temp)
		return false;

	if (sys_hostID[0] == 0 && sys_hostID[1] == 0 && sys_hostID[2] == 0 && sys_hostID[3] == 0)
		return false;

	return true;
}

/*
 *brief   : 从备份寄存器读取另一份本机ID
 *para    : 无
 *return  : 布尔值
 */
bool Read_BKP_HostID(unsigned char *sys_hostID)
{
	for (unsigned char i = 0; i < 4; i++)
		sys_hostID[i] = bkp_read(SYS_HOSTID_BKP_BASE_ADDR + i);

	unsigned char ID_Verify = bkp_read(SYS_HOSTID_BKP_VERIFY);
	unsigned char ID_Verify_Temp = GetCrc8(&sys_hostID[0], 4);

	if (ID_Verify != ID_Verify_Temp)
		return false;

	if (SysHostID[0] == 0 && SysHostID[1] == 0 && SysHostID[2] == 0 && SysHostID[3] == 0)
		return false;

	return true;
}

/*
 *brief   : 保存本机ID到EEPROM中
 *para    : 无
 *return  : 布尔值
 */
bool EP_Save_HostID(unsigned char *sys_hostID)
{
#if (DEVICE_V2_5 || E30_DEVICE_V1_0)
	EP_Write_Enable();
#endif

	for (unsigned char i = 0; i < 4; i++)
		EEPROM1024.write(EP_SYS_HOSTID_BASE_ADDR + i, sys_hostID[i]);

	unsigned char ID_Verify = GetCrc8(&sys_hostID[0], 4);

	EEPROM1024.write(EP_SYS_HOSTID_VERIFY, ID_Verify);

#if (DEVICE_V2_5 || E30_DEVICE_V1_0)
	EP_Write_Disable();
#endif

	for (unsigned char i = 0; i < 4; i++)
		if (sys_hostID[i] != EEPROM1024.read(EP_SYS_HOSTID_BASE_ADDR + i))
			return false;

	return true;
}

/*
 *brief   : 保存本机ID另一份备份到EEPROM中
 *para    : 无
 *return  : 布尔值
 */
bool EP_Save_BKP_HostID(unsigned char *sys_hostID)
{
#if (DEVICE_V2_5 || E30_DEVICE_V1_0)
	EP_Write_Enable();
#endif

	for (unsigned char i = 0; i < 4; i++)
		EEPROM1024.write(EP_SYS_HOSTID_BKP_BASE_ADDR + i, sys_hostID[i]);

	unsigned char ID_Verify = GetCrc8(&sys_hostID[0], 4);

	EEPROM1024.write(EP_SYS_HOSTID_BKP_VERIFY, ID_Verify);

#if (DEVICE_V2_5 || E30_DEVICE_V1_0)
	EP_Write_Disable();
#endif

	for (unsigned char i = 0; i < 4; i++)
		if (sys_hostID[i] != EEPROM1024.read(EP_SYS_HOSTID_BKP_BASE_ADDR + i))
			return false;

	return true;
}

/*
 *brief   : 从EEPROM读取一份本机ID
 *para    : 无
 *return  : 布尔值
 */
bool EP_Read_HostID(unsigned char *sys_hostID)
{
	for (unsigned char i = 0; i < 4; i++)
		sys_hostID[i] = EEPROM1024.read(EP_SYS_HOSTID_BASE_ADDR + i);

	unsigned char ID_Verify = EEPROM1024.read(EP_SYS_HOSTID_VERIFY);
	unsigned char ID_Verify_Temp = GetCrc8(&sys_hostID[0], 4);

	if (ID_Verify != ID_Verify_Temp)
		return false;

	if (sys_hostID[0] == 0 && sys_hostID[1] == 0 && sys_hostID[2] == 0 && sys_hostID[3] == 0)
		return false;

	return true;
}

/*
 *brief   : 从EEPROM读取另一份本机ID
 *para    : 无
 *return  : 布尔值
 */
bool EP_Read_BKP_HostID(unsigned char *sys_hostID)
{
	for (unsigned char i = 0; i < 4; i++)
		sys_hostID[i] = EEPROM1024.read(EP_SYS_HOSTID_BKP_BASE_ADDR + i);

	unsigned char ID_Verify = EEPROM1024.read(EP_SYS_HOSTID_BKP_VERIFY);
	unsigned char ID_Verify_Temp = GetCrc8(&sys_hostID[0], 4);

	if (ID_Verify != ID_Verify_Temp)
		return false;

	if (sys_hostID[0] == 0 && sys_hostID[1] == 0 && sys_hostID[2] == 0 && sys_hostID[3] == 0)
		return false;

	return true;
}

bool System_ID_Self_Check(unsigned char *sys_hostID)
{
	if (Read_BKP_HostID(sys_hostID) && Read_HostID(sys_hostID) && EP_Read_HostID(sys_hostID) && EP_Read_BKP_HostID(sys_hostID))
	{
		Serial.println("All Save OK...");
		delay(100);
		return true;
	}
	else if (Read_BKP_HostID(sys_hostID) && Read_HostID(sys_hostID))
	{
		Serial.println("Read host ID and host backup ID OK but read EEPROM failed!");
		EP_Save_HostID(sys_hostID);
		EP_Save_BKP_HostID(sys_hostID);
		delay(100);
		return true;
	}
	else if (EP_Read_HostID(sys_hostID) && EP_Read_BKP_HostID(sys_hostID))
	{
		Serial.println("Read EEPROM host ID OK but read host ID and host backup ID failed!");
		Save_HostID(sys_hostID);
		Save_BKP_HostID(sys_hostID);
		delay(100);
		return true;
	}
	else if (Read_HostID(sys_hostID))
	{
		Serial.println("Only read host ID OK!");
		Save_BKP_HostID(sys_hostID);
		EP_Save_HostID(sys_hostID);
		EP_Save_BKP_HostID(sys_hostID);
		delay(100);
		return true;
	}
	else if (Read_BKP_HostID(sys_hostID))
	{
		Serial.println("Only read host backup ID OK!");
		Save_HostID(sys_hostID);
		EP_Save_HostID(sys_hostID);
		EP_Save_BKP_HostID(sys_hostID);
		delay(100);
		return true;
	}
	else if (EP_Read_HostID(sys_hostID))
	{
		Serial.println("Only read EP host ID OK!");
		Save_HostID(sys_hostID);
		Save_BKP_HostID(sys_hostID);
		EP_Save_BKP_HostID(sys_hostID);
		delay(100);
		return true;
	}
	else if (EP_Read_BKP_HostID(sys_hostID))
	{
		Serial.println("Only read EP host backup ID OK!");
		Save_HostID(sys_hostID);
		Save_BKP_HostID(sys_hostID);
		EP_Save_HostID(sys_hostID);
		delay(100);
		return true;
	}
	else
	{
		Serial.println("All hostID ERROR!");
		Clear_SYS_HOSTID();
		delay(100);
		return false;
	}
}

bool Save_System_ID(unsigned char *sys_hostID)
{
	unsigned char OverTime = 0;
	unsigned char Save_Times = 0;

	do
	{
		if (Save_HostID(sys_hostID))
		{
			Serial.println("Save Reg OK...");
			delay(100);
			Save_Times++;
		}

		if (EP_Save_HostID(sys_hostID))
		{
			Serial.println("Save EP OK...");
			delay(100);
			Save_Times++;
		}

		if (Save_BKP_HostID(sys_hostID))
		{
			Serial.println("Save Reg bkp OK...");
			delay(100);
			Save_Times++;
		}

		if (EP_Save_BKP_HostID(sys_hostID))
		{
			Serial.println("Save EP bkp OK...");
			delay(100);
			Save_Times++;
		}

		if (Save_Times >= 2)
			return true;
		else
			OverTime++;

		Save_Times = 0;

	} while (OverTime < 3);

	return false;
}

/*
 *brief   : 清除所有ID
 *para    : 无
 *return  : 无
 */
void Clear_SYS_HOSTID(void)
{
	bkp_enable_writes();

#if (DEVICE_V2_5 || E30_DEVICE_V1_0)
	EP_Write_Enable();
#endif

#if E30_DEVICE_V1_0
	EP_Write_Enable();
#endif

	for (unsigned char i = 0; i < 4; i++)
	{
		bkp_write(SYS_HOSTID_BASE_ADDR + i, 0);
		bkp_write(SYS_HOSTID_BKP_BASE_ADDR + i, 0);
		EEPROM1024.write(EP_SYS_HOSTID_BASE_ADDR + i, 0);
		EEPROM1024.write(EP_SYS_HOSTID_BKP_BASE_ADDR + i, 0);
	}

#if (DEVICE_V2_5 || E30_DEVICE_V1_0)
	EP_Write_Disable();
#endif

#if E30_DEVICE_V1_0
	EP_Write_Disable();
#endif
}

/*
 *brief   : 验证已经储存过的系统参数和目前的新参数是否相同。
 *para    : 无
 *return  : 布尔值
 */
bool Verify_Sys_Para(void)
{
	int acquisition_temp;
	int transmit_temp;
	int run_mode_temp;
	unsigned char location_flag_temp;

	// position_temp = EEPROM1024.read(SYS_POSITION_HIGH_ADDR) << 8;
	// position_temp |= EEPROM1024.read(SYS_POSITION_LOW_ADDR);

	acquisition_temp = EEPROM1024.read(SYS_ACQUISITION_CYCLE_HIGH_ADDR) << 8;
	acquisition_temp |= EEPROM1024.read(SYS_ACQUISITION_CYCLE_LOW_ADDR);

	transmit_temp = EEPROM1024.read(SYS_TRANSMIT_CYCLE_HIGH_ADDR) << 8;
	transmit_temp |= EEPROM1024.read(SYS_TRANSMIT_CYCLE_LOW_ADDR);

	run_mode_temp = EEPROM1024.read(SYS_RUN_MODE_HIGH_ADDR) << 8;
	run_mode_temp |= EEPROM1024.read(SYS_RUN_MODE_LOW_ADDR);

	location_flag_temp = EEPROM1024.read(SYS_LOCATION_FLAG_ADDR);

	if (acquisition_temp != Sys_Run_Para.g_Acquisition_Cycle || transmit_temp != Sys_Run_Para.g_Transmit_Cycle || run_mode_temp != Sys_Run_Para.g_Run_Mode || location_flag_temp != Sys_Run_Para.g_Location_Flag)
	{
		Serial.println("服务器下发参数与本设备当前保存的不一致，开始更新参数 <Verify_Sys_Para>");
		Serial.flush();
		return true;
	}
	else
	{
		Serial.println("服务器下发参数与本设备当前保存的一致，无需更新参数 <Verify_Sys_Para>");
		Serial.flush();
		return false;
	}
}

/*
 *brief   : EEPROM创建传感器数据文件
 *para    : 无
 *return  : 无
 */
void Muti_Sensor_Data_Base_Init(void)
{
	unsigned long Sensor_Count = 0;
	EDB_Status Sensor_Result;

#if (DEVICE_V2_5 || E30_DEVICE_V1_0)
	EP_Write_Enable();
#endif

	EpromDb.open(EEPROM_BASE_ADDR);

	Sensor_Count = EpromDb.count();

	if (Sensor_Count == 0)
	{
		Serial.println("EEPROM create sensor data table");
		Sensor_Result = EpromDb.create(EEPROM_BASE_ADDR, TABLE_SIZE, (unsigned int)sizeof(Muti_Sensor_Data));
	}

#if (DEVICE_V2_5 || E30_DEVICE_V1_0)
	EP_Write_Disable();
#endif
}

/*
 *brief   : 读取系统相关参数
 *para    : 无
 *return  : 无
 */
void Read_EEPROM_Server_Param(unsigned char *sys_hostID, System_Run_Parameter *para)
{
	if (Clear_HostID == true)
	{
		for (unsigned char i = 0; i < 4; i++)
			sys_hostID[i] = 0;
	}

	// 传输周期
	para->g_Transmit_Cycle = EEPROM1024.read(SYS_TRANSMIT_CYCLE_HIGH_ADDR) << 8;
	para->g_Transmit_Cycle |= EEPROM1024.read(SYS_TRANSMIT_CYCLE_LOW_ADDR);
	// 收购周期
	para->g_Acquisition_Cycle = EEPROM1024.read(SYS_ACQUISITION_CYCLE_HIGH_ADDR) << 8;
	para->g_Acquisition_Cycle |= EEPROM1024.read(SYS_ACQUISITION_CYCLE_LOW_ADDR);
	// 现在记录计数
	para->g_Now_Record_Count = EEPROM1024.read(SYS_CURRENT_RECORD_HIGH_ADDR) << 8;
	para->g_Now_Record_Count |= EEPROM1024.read(SYS_CURRENT_RECORD_LOW_ADDR);
	// 位置标志
	para->g_Location_Flag = EEPROM1024.read(SYS_LOCATION_FLAG_ADDR);

	// para->Positioning_Mode =  EEPROM1024.read(SYS_POSITION_HIGH_ADDR) << 8;
	// para->Positioning_Mode |=  EEPROM1024.read(SYS_POSITION_LOW_ADDR);

	para->g_Run_Mode = EEPROM1024.read(SYS_RUN_MODE_HIGH_ADDR) << 8;
	para->g_Run_Mode |= EEPROM1024.read(SYS_RUN_MODE_LOW_ADDR);
}

/*
 *brief   : 将采集的数据保存到EEPROM中
 *para    : 无
 *return  : 无
 */
void Save_SensorData_to_EEPROM(void)
{
	Serial.print("EEPROM max record: ");
	Serial.println(EEPROM_MAX_RECORD);

#if (DEVICE_V2_5 || E30_DEVICE_V1_0)
	EP_Write_Enable();
#endif

	EpromDb.open(EEPROM_BASE_ADDR);
	unsigned long Muti_Sensor_Data_Count = EpromDb.count();

	Serial.print("Sensor data cout: ");
	Serial.println(Muti_Sensor_Data_Count);

	if (Muti_Sensor_Data_Count >= EEPROM_MAX_RECORD) //如果新增加的数据笔数超过EEPROM最大保存笔数
		EpromDb.clear();							 //清空数据

	//如果目前数据笔数大于0笔同时小于最大笔数
	if ((Muti_Sensor_Data_Count >= 0) && (Muti_Sensor_Data_Count < EEPROM_MAX_RECORD))
	{
		EDB_Status Sensor_Result = EpromDb.appendRec(EDB_REC Muti_Sensor_Data); //增加一笔数据

		//如果增加储存数据成功
		if (Sensor_Result == EDB_OK)
		{
			Serial.println("Save a Sensor Data done...");
			Sys_Run_Para.g_Send_EP_Data_Flag = true;
		}
		//如果增加储存数据失败，清空数据
		else
		{
			Serial.println("Sensor save falied!");
			Sys_Run_Para.g_Send_EP_Data_Flag = false;
			EpromDb.clear();
		}
	}
	//如果目前的数据笔数小于0，EEPROM异常或损坏，不能存数据到EEPROM，只能采集一笔，发送一笔。
	else
		Sys_Run_Para.g_Send_EP_Data_Flag = false; //用来标识EEPROM损坏与否

#if (DEVICE_V2_5 || E30_DEVICE_V1_0)
	EP_Write_Disable();
#endif
}

/*
 *brief   : 保存得到的系统参数
 *para    : 无
 *return  : 无
 */
void Save_Param_to_EEPROM(void)
{
	Serial.println("开始保存得到的系统参数 <Save_Param_to_EEPROM>");
	Serial.flush();

#if (DEVICE_V2_5 || E30_DEVICE_V1_0)
	EP_Write_Enable();
#endif

	EEPROM1024.write(SYS_ACQUISITION_CYCLE_HIGH_ADDR, highByte(Sys_Run_Para.g_Acquisition_Cycle));
	EEPROM1024.write(SYS_ACQUISITION_CYCLE_LOW_ADDR, lowByte(Sys_Run_Para.g_Acquisition_Cycle));

	EEPROM1024.write(SYS_TRANSMIT_CYCLE_HIGH_ADDR, highByte(Sys_Run_Para.g_Transmit_Cycle));
	EEPROM1024.write(SYS_TRANSMIT_CYCLE_LOW_ADDR, lowByte(Sys_Run_Para.g_Transmit_Cycle));

	EEPROM1024.write(SYS_LOCATION_FLAG_ADDR, Sys_Run_Para.g_Location_Flag);

	// EEPROM1024.write(SYS_POSITION_HIGH_ADDR, highByte(Sys_Run_Para.g_Positioning_Mode));
	// EEPROM1024.write(SYS_POSITION_LOW_ADDR, lowByte(Sys_Run_Para.g_Positioning_Mode));

	EEPROM1024.write(SYS_RUN_MODE_HIGH_ADDR, highByte(Sys_Run_Para.g_Run_Mode));
	EEPROM1024.write(SYS_RUN_MODE_LOW_ADDR, lowByte(Sys_Run_Para.g_Run_Mode));

#if (DEVICE_V2_5 || E30_DEVICE_V1_0)
	EP_Write_Disable();
#endif

	Serial.println("保存完成 <Save_Param_to_EEPROM>");
	Serial.flush();
}

/*
 *brief   : 保存目前已发送的传感器数据笔数
 *para    : 无
 *return  : 无
 */
void Save_Sys_Current_Record(unsigned int now_record)
{
#if (DEVICE_V2_5 || E30_DEVICE_V1_0)
	EP_Write_Enable();
#endif

	EEPROM1024.write(SYS_CURRENT_RECORD_HIGH_ADDR, highByte(now_record));
	EEPROM1024.write(SYS_CURRENT_RECORD_LOW_ADDR, lowByte(now_record));

#if (DEVICE_V2_5 || E30_DEVICE_V1_0)
	EP_Write_Disable();
#endif
}

/*
 *brief   : 读取目前已发送的传感器数据笔数
 *para    : 无
 *return  : 无
 */
unsigned int Read_Sys_Current_Record(void)
{
	unsigned int Cur_Record_Temp;
	Cur_Record_Temp = EEPROM1024.read(SYS_CURRENT_RECORD_HIGH_ADDR) << 8;
	Cur_Record_Temp |= EEPROM1024.read(SYS_CURRENT_RECORD_LOW_ADDR);
	return Cur_Record_Temp;
}

bool Write_ALL_data(unsigned char data)
{
#if (DEVICE_V2_5 || E30_DEVICE_V1_0)
	EP_Write_Enable();
#endif

	for (size_t i = 0; i < TABLE_SIZE; i++)
	{
		EEPROM1024.write(i,data);
		if(!(EEPROM1024.read(i) == data)){
			Serial.println(String("[ERROR!]") + i);
			return false;
		}

		if(i%500 == 0){
			Serial.println(String("i = ") + i);
			Serial.println(String("read[") + i + "]= " + EEPROM1024.read(i));
		}
	}

#if (DEVICE_V2_5 || E30_DEVICE_V1_0)
	EP_Write_Disable();
#endif

	Serial.println("Success");
	return true;
}